items
)。// Day15 - 解析溫度資訊(支援多種 API 結構)
// 回傳內容會包含:temp_c, temp_f, message,以及若有 hourly 則會有 min/max/avg
function toNumber(v){
const n = Number(v);
return (Number.isFinite(n)) ? n : null;
}
// heuristic 將 raw 溫度轉為攝氏(簡單判斷:>200 => K, >70 => F, 否則視為 C)
function rawToCelsius(raw){
const n = toNumber(raw);
if (n === null) return null;
if (n > 200) return n - 273.15; // 很可能是 Kelvin
if (n > 70) return (n - 32) * 5/9; // 很可能是 Fahrenheit
return n; // 否則視為 Celsius
}
function round1(v){
if (v === null || v === undefined) return null;
return Math.round(v*10)/10;
}
return items.map(item => {
try {
const data = item.json || {};
// 優先取常見位置
// Open-Meteo: data.current_weather.temperature
// OpenWeatherMap: data.main.temp
// Generic: data.temperature
let tempRaw = null;
let source = 'unknown';
if (data.current_weather && data.current_weather.temperature !== undefined){
tempRaw = data.current_weather.temperature;
source = 'open-meteo:current_weather';
} else if (data.main && data.main.temp !== undefined){
tempRaw = data.main.temp;
source = 'openweathermap:main.temp';
} else if (data.temperature !== undefined){
tempRaw = data.temperature;
source = 'generic:temperature';
}
// 若有 hourly 陣列(例如 open-meteo 的 hourly.temperature_2m),算 min/max/avg
let hourlyStats = null;
if (data.hourly && Array.isArray(data.hourly.temperature_2m) && data.hourly.temperature_2m.length > 0){
const arr = data.hourly.temperature_2m.map(v => toNumber(v)).filter(v => v !== null);
if (arr.length > 0){
const sum = arr.reduce((s,x)=>s+x,0);
const avg = sum / arr.length;
const min = Math.min(...arr);
const max = Math.max(...arr);
hourlyStats = {
min_c: round1(rawToCelsius(min)),
max_c: round1(rawToCelsius(max)),
avg_c: round1(rawToCelsius(avg)),
raw_count: arr.length
};
}
}
// 如果沒有直接 tempRaw,但有 hourly 可從 current index 或第一筆取
if (tempRaw === null && data.current_weather && data.current_weather.temperature !== undefined){
tempRaw = data.current_weather.temperature;
source = 'open-meteo:current_weather';
}
// 解析 temp
const tempC = (tempRaw !== null) ? round1(rawToCelsius(tempRaw)) : null;
const tempF = (tempC !== null) ? round1(tempC * 9/5 + 32) : null;
// 取得時間、地點等可讀欄位(盡量找出現有資料)
const time = (data.current_weather && data.current_weather.time) || data.dt || data.time || null;
const lat = data.latitude || (data.location && data.location.lat) || null;
const lon = data.longitude || (data.location && data.location.lon) || null;
// 組成可讀訊息(用 template literal 保留換行)
let msgLines = [];
if (lat !== null && lon !== null) msgLines.push(`地點: (${lat}, ${lon})`);
if (time) msgLines.push(`時間: ${time}`);
if (tempC !== null) msgLines.push(`現在溫度: ${tempC}°C (${tempF}°F)`);
else msgLines.push(`現在溫度: N/A`);
if (hourlyStats){
msgLines.push(`今日(hourly)最小: ${hourlyStats.min_c}°C,最大: ${hourlyStats.max_c}°C,平均: ${hourlyStats.avg_c}°C`);
}
msgLines.push(`原始來源: ${source}`);
const message = msgLines.join('\n'); // 保留換行
// 回傳結構:message(可直接顯示或寄發)、以及個別欄位方便後續使用
return {
json: {
temp_raw: tempRaw,
temp_c: tempC,
temp_f: tempF,
hourly: hourlyStats,
message,
raw: data
}
};
} catch (err){
return {
json: {
error: true,
message: `解析錯誤: ${err.message}`,
raw: item.json
}
};
}
});
打開 workflow(例如 Day14_Weather_API
),在 Get Weather 節點後新增一個 Function 節點,命名 Parse Temp
。
把上面程式碼貼進 Parse Temp
的程式碼區(完全取代預設內容)。
把 Get Weather
的輸出拉線連到 Parse Temp
。
在畫面右上點 Save。
測試方法:
開啟 Executions / Execution Log → 點剛剛的執行 → 展開 Parse Temp
的 Output → 會看到 message
欄位內有多行可讀文字(如果 UI 有顯示為單行帶 \n
,可以點開值或複製貼到記事本確認換行;外部寄信 / Telegram / Slack 等通常會正確呈現換行)。
input (Open-Meteo):
[
{
"latitude": 25,
"longitude": 121.625,
"generationtime_ms": 0.037670135498046875,
"utc_offset_seconds": 28800,
"timezone": "Asia/Taipei",
"timezone_abbreviation": "GMT+8",
"elevation": 12,
"current_weather_units": {
"time": "iso8601",
"interval": "seconds",
"temperature": "°C",
"windspeed": "km/h",
"winddirection": "°",
"is_day": "",
"weathercode": "wmo code"
},
"current_weather": {
"time": "2025-09-27T21:30",
"interval": 900,
"temperature": 27.6,
"windspeed": 6.8,
"winddirection": 87,
"is_day": 0,
"weathercode": 1
}
}
]
Function output
[
{
"temp_raw": 27.6,
"temp_c": 27.6,
"temp_f": 81.7,
"hourly": null,
"message": "地點: (25, 121.625)\n時間: 2025-09-27T21:30\n現在溫度: 27.6°C (81.7°F)\n原始來源: open-meteo:current_weather",
"raw": {
"latitude": 25,
"longitude": 121.625,
"generationtime_ms": 0.037670135498046875,
"utc_offset_seconds": 28800,
"timezone": "Asia/Taipei",
"timezone_abbreviation": "GMT+8",
"elevation": 12,
"current_weather_units": {
"time": "iso8601",
"interval": "seconds",
"temperature": "°C",
"windspeed": "km/h",
"winddirection": "°",
"is_day": "",
"weathercode": "wmo code"
},
"current_weather": {
"time": "2025-09-27T21:30",
"interval": 900,
"temperature": 27.6,
"windspeed": 6.8,
"winddirection": 87,
"is_day": 0,
"weathercode": 1
}
}
}
]
在 Email / Telegram 發送 message
時會看到真正換行效果。